package com.focusai.efairy.model.request;


import android.text.TextUtils;

import com.focusai.efairy.model.file.FileInfo;
import com.focusai.efairy.network.NetworkResponse;
import com.focusai.efairy.network.Response;
import com.focusai.efairy.network.exception.NetworkException;
import com.focusai.efairy.network.exception.ParseException;
import com.focusai.efairy.network.request.base.Request;
import com.focusai.efairy.utils.FileDispositionFormat;
import com.focusai.efairy.utils.FileUtils;

import org.apache.commons.io.IOUtils;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.URLDecoder;
import java.util.Map;


public class DownloadFileRequest extends Request<String> {

    public interface IDownlaodCallback {
        void onDownLoadFileSuccess();
        void onDownLoadFileFailed();
        void onDownLoadFileProcess(int percent);
    }
    private FileInfo fileInfo;
    private IDownlaodCallback mCallback;
    public DownloadFileRequest(FileInfo fileInfo,IDownlaodCallback callback){
        super(Method.GET,fileInfo.downLoadUrl,null);
        mCallback = callback;
        this.fileInfo = fileInfo;
    }


    @Override
    public Response<String> parseNetworkResponse(NetworkResponse networkResponse) {
        if (null == networkResponse) {
            return null;
        }
        InputStream inputStream = null;
        FileOutputStream outputStream = null;
        try {
            refreshFileInfo(fileInfo, networkResponse.getHeaders());

            inputStream = networkResponse.getInputStream();
            outputStream = getFileOutputStream(FileUtils.getKdFileTmpPath(fileInfo));
            writeFileStream(inputStream,outputStream,fileInfo.fileSize);
            if(null != mCallback && !mStop){
                mCallback.onDownLoadFileSuccess();
            }
            return Response.success(null);
        } catch (Exception e) {
            e.printStackTrace();
            if(null != mCallback){
                mCallback.onDownLoadFileFailed();
            }
            return Response.error(new NetworkException(e));
        } finally {
            IOUtils.closeQuietly(inputStream);
            IOUtils.closeQuietly(outputStream);
        }
    }

    @Override
    protected String parse(String result) throws ParseException {
        return null;
    }

    private void refreshFileInfo(FileInfo fileInfo,Map<String, String> extHeaders)throws Exception{
        if(null == extHeaders ){
            return;
        }

        if(null != extHeaders.get("Content-Disposition")){
            String disposition	= URLDecoder.decode(extHeaders.get("Content-Disposition"),"UTF-8");
            String fileName = FileDispositionFormat.getFileName(disposition);
            String fileExt = FileDispositionFormat.getFileExt(disposition);
            if(!TextUtils.isEmpty(fileName)){
                fileInfo.fileName = fileName;
            }
        }

        if(null != extHeaders.get("filesize")){
            fileInfo.fileSize = Long.parseLong(extHeaders.get("filesize"));
        }else if(null != extHeaders.get("Content-Length")){
            fileInfo.fileSize = Long.parseLong(extHeaders.get("Content-Length"));
        }else if(null != extHeaders.get("content-length")){
            fileInfo.fileSize = Long.parseLong(extHeaders.get("content-length"));
        }
    }

    private FileOutputStream getFileOutputStream(String Path) throws IOException {
        File file_ = new File(Path);
        file_.getParentFile().mkdirs();
        if (file_.exists()) {
            file_.delete();
        }
        new File(Path).createNewFile();
        return new FileOutputStream(Path);
    }

    private static int BUFFER_SIZE = 20 * 1024;
    private void writeFileStream(InputStream inputStream,FileOutputStream outputStream, long fileLength) throws Exception{
        byte[] buffer = new byte[BUFFER_SIZE];
        long readLength = 0;
        int count = 0;
        int temp = 0;
        int percent = 0;
        while (!mStop && (count = inputStream.read(buffer)) != -1) {
            judgeNeedPause();
            outputStream.write(buffer, 0, count);
            readLength += count;
            if(null != mCallback && fileLength > 0){
                percent = (int) (readLength * 100 / fileLength);
                if (percent >= temp){
                    temp ++;
                    mCallback.onDownLoadFileProcess(percent);
                }
            }
        }
    }

    private final Object mPauseLock = new Object();
    private boolean mPause = false;
    private boolean mStop = false;
    private void judgeNeedPause(){
        synchronized (mPauseLock) {
            while (mPause) {
                try {
                    mPauseLock.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public void pauseDownLoad(){
        mPause = true;
    }

    public void resumeDownload(){
        mPause = false;
        synchronized (mPauseLock) {
            mPauseLock.notifyAll();
        }
    }

    public void stopDownload(){
        mStop = true;
        resumeDownload();
        new File(FileUtils.getKdFileTmpPath(fileInfo)).delete();
    }

}
